home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / CLASSSRC.PAK / USTRING.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  11KB  |  531 lines

  1. //----------------------------------------------------------------------------
  2. // Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
  3. //
  4. //$Revision:   5.8  $
  5. //
  6. // TString (& TUString) implementation (others functions are inline)
  7. //----------------------------------------------------------------------------
  8. #include <winsys/pch.h>
  9. #include <winsys/string.h>
  10. #include <services/memory.h>
  11. #include <string.h>
  12. #include <tchar.h>
  13.  
  14. TUString TUString::Null;   // null TAutoStrings reference this object
  15.  
  16. #if defined(BI_HAS_WCHAR)
  17. //
  18. // Take a wide char string & return an ANSI string in a new'd char[] buffer
  19. //
  20. char* TUString::ConvertWtoA(const wchar_t* src, size_t len)
  21. {
  22.   size_t size = WideCharToMultiByte(CP_ACP, 0, src, len, 0, 0, 0, 0);
  23.   char* dst = new char[size + (len != -1)];  // room for null if fixed size
  24.   size = WideCharToMultiByte(CP_ACP, 0, src, len, dst, size, 0, 0);
  25.   if (len != -1)
  26.     dst[size] = 0;
  27.   return dst;
  28. }
  29.  
  30. //
  31. // Take an ANSI char string & return a wide string in a new'd wchar_t[] buffer
  32. //
  33. wchar_t* TUString::ConvertAtoW(const char* src, size_t len)
  34. {
  35.   size_t size = MultiByteToWideChar(CP_ACP, 0, src, len, 0, 0);
  36.   wchar_t* dst = new wchar_t[size + (len != -1)];
  37.   size = MultiByteToWideChar(CP_ACP, 0, src, len, dst, size);
  38.   if (len != -1)
  39.     dst[size] = 0;
  40.   return dst;
  41. }
  42. #endif
  43.  
  44. //------------------------------------------------------------------------
  45.  
  46. //
  47. // Change UString to isCopy regardless of current type
  48. //
  49. _TCHAR* TUString::ChangeToCopy()
  50. {
  51.   _TCHAR* dst = 0;
  52.   const _TCHAR far* src;
  53.   int len;
  54.   switch (Kind) {
  55.     case isNull:
  56.       return 0;
  57.     case isConst:
  58.       src = Const;
  59.       len = _tcslen(Const);
  60.       break;
  61.     case isCopy:
  62.       return Copy;
  63. #if defined(BI_HAS_WCHAR)
  64.     case isWConst:
  65.       dst = ConvertWtoA(WConst);
  66.       break;
  67.     case isWCopy:
  68.       dst = ConvertWtoA(WCopy);
  69.       delete[] WCopy;
  70.       break;
  71. #endif
  72. #if defined(BI_OLECHAR_WIDE)
  73.     case isBstr:
  74.     case isExtBstr:
  75.       dst = ConvertWtoA(Bstr, ::SysStringLen(Bstr));
  76.       break;
  77. #else
  78.     case isBstr:
  79.     case isExtBstr:
  80.       src = Bstr;
  81.       len = ::SysStringLen(Bstr);
  82.       break;
  83. #endif
  84.     case isString:
  85.       src = ((string*)&String)->c_str();
  86.       len = ((string*)&String)->length();
  87.   }
  88.   if (!dst) {
  89.     dst = new _TCHAR[len+1];
  90.     memcpy(dst, src, len+1);
  91.   }
  92.   if (Kind == isBstr)
  93.     ::SysFreeString(Bstr);
  94.   Kind = isCopy;
  95.   Copy = dst;
  96.   return Copy;
  97. }
  98.  
  99. #if defined(BI_HAS_WCHAR)
  100. //
  101. // Change UString to isWCopy regardless of current type
  102. //
  103. wchar_t* TUString::ChangeToWCopy()
  104. {
  105.   wchar_t* dst = 0;
  106.   const wchar_t* src;
  107.   int len;
  108.   switch (Kind) {
  109.     case isNull:
  110.       return 0;
  111.     case isConst:
  112.       dst = ConvertAtoW(Const);
  113.       break;
  114.     case isCopy:
  115.       dst = ConvertAtoW(Copy);
  116.       delete[] Copy;
  117.       break;
  118.     case isWConst:
  119.       src = WConst;
  120.       len = _tcslen(WConst);
  121.       break;
  122.     case isWCopy:
  123.       return WCopy;
  124. #if defined(BI_OLECHAR_WIDE)
  125.     case isBstr:
  126.     case isExtBstr:
  127.       src = Bstr;
  128.       len = ::SysStringLen(Bstr);
  129.       break;
  130. #else                // This case probably never happens
  131.     case isBstr:
  132.     case isExtBstr:
  133.       dst = ConvertAtoW(Bstr, ::SysStringLen(Bstr));
  134.       break;
  135. #endif
  136.     case isString:
  137.       dst = ConvertAtoW(((string*)&String)->c_str(), ((string*)&String)->length());
  138.   }
  139.   if (!dst) {
  140.     dst = new wchar_t[len+1];
  141.     memcpy(dst, src, (len+1) * sizeof(wchar_t));
  142.   }
  143.   if (Kind == isBstr)
  144.     ::SysFreeString(Bstr);
  145.   Kind = isWCopy;
  146.   WCopy = dst;
  147.   return WCopy;
  148. }
  149. #endif
  150.  
  151. //------------------------------------------------------------------------
  152. // inline ctors used by Create functions.
  153. // Note: these are never made public or exported from this unit
  154. //
  155.  
  156. //
  157. inline TUString::TUString(const _TCHAR far& str)
  158. :
  159.   Kind(isConst),
  160.   Const(&str),
  161.   RefCnt(1),
  162.   Lang(0)
  163. {
  164. }
  165.  
  166. //
  167. inline TUString::TUString(_TCHAR& str)
  168. :
  169.   Kind(isCopy), RefCnt(1), Lang(0)
  170. {
  171.   Copy = new _TCHAR[_tcslen(&str)+1];
  172.   _tcscpy(Copy, &str);
  173. }
  174.  
  175. #if defined(BI_HAS_WCHAR)
  176.  
  177. //
  178. inline TUString::TUString(const wchar_t& str)
  179. :
  180.   Kind(isWConst),
  181.   WConst(&str),
  182.   RefCnt(1),
  183.   Lang(0)
  184. {
  185. }
  186.  
  187. //
  188. inline TUString::TUString(wchar_t& str)
  189. :
  190.   Kind(isWCopy),
  191.   RefCnt(1),
  192.   Lang(0)
  193. {
  194.   WCopy = new wchar_t[_tcslen(&str)+1];
  195.   _tcscpy(WCopy, &str);
  196. }
  197. #endif
  198.  
  199. //
  200. inline TUString::TUString(BSTR str, bool loan, TLangId lang)
  201. :
  202.   Kind(loan ? isExtBstr : isBstr),
  203.   Bstr(str),
  204.   RefCnt(int16(loan ? 2 : 1)),
  205.   Lang(lang)
  206. {
  207. }
  208.  
  209. //
  210. inline TUString::TUString(TSysStr& str, bool loan, TLangId lang)
  211. :
  212.   Kind(loan ? isExtBstr : isBstr),
  213.   Bstr(str.operator BSTR()),
  214.   RefCnt(int16(loan ? 2 : 1)),
  215.   Lang(lang)
  216. {
  217. }
  218.  
  219. //
  220. inline void* operator new(size_t, TStringRef** p) {return p;}
  221.  
  222. //
  223. inline TUString::TUString(const string& str)
  224. :
  225.   Kind(isString), RefCnt(1), Lang(0)
  226. {
  227.   new(&String) string(str);
  228. }
  229.  
  230. //------------------------------------------------------------------------
  231. // Static creation, or factory functions return pointers to new UStrings, or
  232. // pointers to the Null UString
  233. //
  234.  
  235. //
  236. TUString* TUString::Create(const _TCHAR far* str)
  237. {
  238.   return str /*&& *str*/ ? new TUString(*str) : &++Null;
  239. }
  240.  
  241. //
  242. TUString* TUString::Create(_TCHAR* str)
  243. {
  244.   return str /*&& *str*/ ? new TUString(*str) : &++Null;
  245. }
  246.  
  247. #if defined(BI_HAS_WCHAR)
  248.  
  249. //
  250. TUString* TUString::Create(const wchar_t* str)
  251. {
  252.   return str /*&& *str*/ ? new TUString(*str) : &++Null;
  253. }
  254.  
  255. //
  256. TUString* TUString::Create(wchar_t* str)
  257. {
  258.   return str /*&& *str*/ ? new TUString(*str) : &++Null;
  259. }
  260. #endif
  261.  
  262. //
  263. TUString* TUString::Create(BSTR str, bool loan, TLangId lang)
  264. {
  265.   if (str && ::SysStringLen(str))
  266.     return new TUString(str, loan, lang);
  267.   if (!loan)
  268.     ::SysFreeString(str);
  269.   return &++Null;
  270. }
  271.  
  272. //
  273. TUString* TUString::Create(TSysStr& str, bool loan, TLangId lang)
  274. {
  275.   return Create(str.operator BSTR(), loan, lang);
  276. }
  277.  
  278. //
  279. TUString* TUString::Create(const string& str)
  280. {
  281.   return str.length() ? new TUString(str) : &++Null;
  282. }
  283.  
  284. //------------------------------------------------------------------------
  285. //
  286. //
  287.  
  288. //
  289. TUString* TUString::Assign(const TUString& s)
  290. {
  291.   if (RefCnt == 1 && Kind != isNull && Kind != isExtBstr)
  292.     Free();
  293.   else
  294.     --*this;
  295.  
  296.   CONST_CAST(TUString&,s).RefCnt++;
  297.   return &CONST_CAST(TUString&,s);
  298. }
  299.  
  300. //
  301. TUString* TUString::Assign(const string& s)
  302. {
  303.   if (s.length() && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
  304.     Free();
  305.     Kind = isString;
  306.     new(&String) string(s);
  307.     return this;
  308.   }
  309.   else {
  310.     --*this;
  311.     return Create(s);
  312.   }
  313. }
  314.  
  315. //
  316. TUString* TUString::Assign(const _TCHAR far* s)
  317. {
  318.   if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
  319.     Free();
  320.     Kind = isConst;
  321.     Const = s;
  322.     return this;
  323.   }
  324.   else {
  325.     --*this;
  326.     return Create(s);
  327.   }
  328. }
  329.  
  330. //
  331. TUString* TUString::Assign(_TCHAR* s)
  332. {
  333.   if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
  334.     Free();
  335.     Kind = isCopy;
  336.     Copy = new _TCHAR[_tcslen(s)+1];
  337.     _tcscpy(Copy, s);
  338.     return this;
  339.   }
  340.   else {
  341.     --*this;
  342.     return Create(s);
  343.   }
  344. }
  345.  
  346. #if defined(BI_HAS_WCHAR)
  347.  
  348. //
  349. TUString* TUString::Assign(const wchar_t* s)
  350. {
  351.   if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
  352.     Free();
  353.     Kind = isWConst;
  354.     WConst = s;
  355.     return this;
  356.   }
  357.   else {
  358.     --*this;
  359.     return Create(s);
  360.   }
  361. }
  362.  
  363. //
  364. TUString* TUString::Assign(wchar_t* s)
  365. {
  366.   if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
  367.     Free();
  368.     Kind = isWCopy;
  369.     WCopy = new wchar_t[_tcslen(s)+1];
  370.     _tcscpy(WCopy, s);
  371.     return this;
  372.   }
  373.   else {
  374.     --*this;
  375.     return Create(s);
  376.   }
  377. }
  378. #endif
  379.  
  380. //
  381. TUString* TUString::Assign(BSTR str, TLangId lang)
  382. {
  383.   if (RefCnt==1 && Kind != isNull && Kind != isExtBstr) {
  384.     Free();
  385.     Kind = isBstr;
  386.     Bstr = str;
  387.     Lang = lang;
  388.     if (Bstr && ::SysStringLen(Bstr))
  389.       return this;
  390.     delete this;
  391.     return &++Null;
  392.   }
  393.   else {
  394.     --*this;
  395.     return Create(str, false, lang);
  396.   }
  397. }
  398.  
  399. //------------------------------------------------------------------------
  400.  
  401. //
  402. TUString::operator const _TCHAR far*() const
  403. {
  404.   switch (Kind) {
  405.     case isNull:    return 0;
  406.     case isConst:   return Const;
  407.     case isCopy:    return Copy;
  408.     case isString:  return ((string*)&String)->c_str();
  409. #if defined(BI_OLECHAR_WIDE)
  410.     case isBstr:
  411.     case isExtBstr: return CONST_CAST(TUString*,this)->ChangeToCopy();
  412. #else
  413.     case isBstr:
  414.     case isExtBstr: return Bstr;
  415. #endif
  416.     case isWConst:
  417.     case isWCopy:   return CONST_CAST(TUString*,this)->ChangeToCopy();
  418.   }
  419.   return 0; // suppress warning
  420. }
  421.  
  422. //
  423. TUString::operator _TCHAR*()
  424. {
  425.   return ChangeToCopy();
  426. }
  427.  
  428. #if defined(BI_HAS_WCHAR)
  429.  
  430. //
  431. TUString::operator const wchar_t*() const
  432. {
  433.   switch (Kind) {
  434.     case isNull:    return 0;
  435.     case isWConst:  return WConst;
  436.     case isWCopy:   return WCopy;
  437. #if defined(BI_OLECHAR_WIDE)
  438.     case isBstr:
  439.     case isExtBstr: return Bstr;
  440. #else
  441.     case isBstr:
  442.     case isExtBstr: return CONST_CAST(TUString*,this)->ChangeToWCopy();
  443. #endif
  444.     case isConst:
  445.     case isCopy:
  446.     case isString:  return CONST_CAST(TUString*,this)->ChangeToWCopy();
  447.   }
  448.   return 0; // suppress warning
  449. }
  450.  
  451. //
  452. TUString::operator wchar_t*()
  453. {
  454.   return ChangeToWCopy();
  455. }
  456. #endif
  457.  
  458. //------------------------------------------------------------------------
  459.  
  460. //
  461. //
  462. //
  463. int TUString::Length() const
  464. {
  465.   switch (Kind) {
  466.     case isNull:    return 0;
  467. #if defined(BI_HAS_WCHAR)
  468.     case isWConst:  return _tcslen(WConst);
  469.     case isWCopy:   return _tcslen(WCopy);
  470. #endif
  471.     case isBstr:
  472.     case isExtBstr: return ::SysStringLen(Bstr);
  473.     case isConst:   return _tcslen(Const);
  474.     case isCopy:    return _tcslen(Copy);
  475.     case isString:  return ((string*)&String)->length();
  476.   }
  477.   return 0; // suppress warning
  478. }
  479.  
  480. //------------------------------------------------------------------------
  481.  
  482. //
  483. // Revoke BSTR ownership from this UString, i.e. make this UString relinquish
  484. //
  485. void TUString::RevokeBstr(BSTR s)
  486. {
  487.   if (Kind != isExtBstr || Bstr != s)  // Don't have it anymore
  488.     return;
  489.   if (RefCnt == 1) {   // We go away. Assume that our envelope knows about this!
  490.     Kind = isNull;
  491.     delete this;
  492.     return;
  493.   }
  494. #if defined(BI_OLECHAR_WIDE)
  495.   ChangeToWCopy();     // Make an appropriate copy of it
  496. #else
  497.   ChangeToCopy();
  498. #endif
  499. }
  500.  
  501. //
  502. // Pass BSTR ownership to this UString
  503. //
  504. void TUString::ReleaseBstr(BSTR s)
  505. {
  506.   if (Kind == isExtBstr && Bstr == s) {
  507.     Kind = isBstr;
  508.     --*this;
  509.   }
  510.   else       // Has been overwritten with converted type, don't need anymore
  511.     ::SysFreeString(s);
  512. }
  513.  
  514. //
  515. // Free any resources held by this UString. Union & Kind left in random state;
  516. // must be reinitialized before use.
  517. //
  518. void TUString::Free()
  519. {
  520.   switch (Kind) {
  521.     case isCopy:    delete[] Copy; break;
  522. #if defined(BI_HAS_WCHAR)
  523.     case isWCopy:   delete[] WCopy; break;
  524. #endif
  525.     case isBstr:    ::SysFreeString(Bstr); break;
  526.     case isString:  ((string*)&String)->string::~string();
  527.   }
  528.   Lang = 0;
  529. //Kind = isNull;  // for safety, not really needed
  530. }
  531.